#pragma once
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <string.h>
#include <iostream>
#include "Server.h"
#include "User.h"
#include "ReadWrite.h"

#define MAX_PLAYERS 10

using namespace std;

void * runListener(void *);

class Listener {

public:

	int passiveSock;
	struct sockaddr_in server;
	Server* serverPointer;

	//tworzy obiekt klasy Listener, który przywi¹¿e gniazdo do danego portu i ustawi je na pasywne //socket, bind, listen
	Listener(int port, Server *serverPointer_) {
		serverPointer = serverPointer_;
		server.sin_family = AF_INET;
		server.sin_addr.s_addr = INADDR_ANY;
		server.sin_port = htons(port);

		passiveSock = socket(AF_INET, SOCK_STREAM, 0);

		if (passiveSock == -1) {
			perror("Otwieranie socketu");
			exit(1);
		}

		if (bind(passiveSock, (struct sockaddr *) &server, sizeof server) == -1) {
			perror("Bindowanie socketu");
			exit(1);
		}

	}
	;

	~Listener() {
		cout << "KONIEC Listenera!\n";
		close(passiveSock);
	}
	//Metoda "uruchamiająca" Listener
	void run(void) {

		pthread_t thread[MAX_PLAYERS];
		UserSocket userSocket[MAX_PLAYERS];
		int i = 0;
		cout << ("Listener: Szukam akceptacji\n");
		//Nasłuchiwanie na porcie (10 klientów może oczekiwać na połączenie jednocześnie)
		listen(passiveSock, 10);
		//Pętla akceptująca połączenia, wywołująca tworzenie klienta oraz tworząca wątek odbierania danych
		while (1) {
			userSocket[i].sock = accept(passiveSock, (struct sockaddr *) 0,
					(socklen_t*) 0);

			userSocket[i].user_ = serverPointer->connectClient(
					userSocket[i].sock);

			//Utworzenie wątku odbierania danych
			pthread_create(&thread[i], NULL, readData, (void*) &userSocket[i]);

			i++;
		}
	}
	;
	//Zamknięcie zaasociowanego gniazda
	void closePassiveSocket() {
		close(passiveSock);
	}
	;
};

